Imports Microsoft.VisualBasic
Imports System.data
Imports System.Collections.Generic
Imports System.Configuration.Provider

Public MustInherit Class ForumProvider : Inherits ProviderBase
    Private Shared _instance As ForumProvider

    ' Returns an instance of the provider type specified in the config file
    Public Shared ReadOnly Property Instance() As ForumProvider
        Get
            If IsNothing(_instance) Then

            End If
            Return _instance
        End Get
    End Property

    ' ==========
    ' Constructor
    ' ==========
    Public Sub New()
    End Sub

    ' ==========
    ' Override methods
    ' ==========

    ' methods that work with forums
    Public MustOverride Function GetForums() As List(Of DataTypes.ForumDetails)
    Public MustOverride Function GetForumByID(ByVal forumID As String) As DataTypes.ForumDetails
    Public MustOverride Function DeleteForum(ByVal forumID As String) As Boolean
    Public MustOverride Function UpdateForum(ByVal forum As DataTypes.ForumDetails) As Boolean
    Public MustOverride Function InsertForum(ByVal title As String, ByVal moderated As Boolean, _
                ByVal importance As Integer, ByVal description As String, ByVal imageUrl As String, ByVal Username As String) As String

    ' methods that work with posts
    Public MustOverride Function GetThreads(ByVal forumID As String, ByVal sortExpression As String, _
        ByVal pageIndex As Integer, ByVal pageSize As Integer) As List(Of DataTypes.PostDetails)
    Public MustOverride Function GetThreadCount(ByVal forumID As String) As Integer
    Public MustOverride Function GetThreads(ByVal forumID As String) As List(Of DataTypes.PostDetails)
    Public MustOverride Function GetThreads(ByVal sortExpression As String, _
        ByVal pageIndex As Integer, ByVal pageSize As Integer) As List(Of DataTypes.PostDetails)
    Public MustOverride Function GetThreadCount() As Integer
    Public MustOverride Function GetThreadByID(ByVal threadPostID As String) As List(Of DataTypes.PostDetails)
    Public MustOverride Function GetPostCountByThread(ByVal threadPostID As String) As Integer
    Public MustOverride Function GetPostCountByForum(ByVal forumID As String) As Integer
    Public MustOverride Function GetUnapprovedPosts() As List(Of DataTypes.PostDetails)
    Public MustOverride Function GetPostByID(ByVal postID As String) As DataTypes.PostDetails
    Public MustOverride Function DeletePost(ByVal postID As String) As Boolean
    Public MustOverride Function UpdatePost(ByVal post As DataTypes.PostDetails) As Boolean
    Public MustOverride Function InsertPost(ByVal post As DataTypes.PostDetails) As String
    Public MustOverride Function ApprovePost(ByVal postID As String) As Boolean
    Public MustOverride Function CloseThread(ByVal threadPostID As String) As Boolean
    Public MustOverride Function MoveThread(ByVal threadPostID As String, ByVal forumID As String) As Boolean
    Public MustOverride Function IncrementPostViewCount(ByVal postID As String) As Boolean
    Public MustOverride Function GetPostBody(ByVal postID As String) As String
    Public MustOverride Function GetLatestPost(ByVal forumID As String) As DataTypes.PostDetails 
    ' Returns a valid sort expression
    Public Overridable Function EnsureValidSortExpression(ByVal sortExpression As String) As String
        If String.IsNullOrEmpty(sortExpression) Then
            Return "_Posts.LastPostDate DESC"
        End If

        Dim sortExpr As String = sortExpression.ToLower()
        If Not sortExpr.Equals("lastpostdate") AndAlso Not sortExpr.Equals("lastpostdate asc") AndAlso _
            Not sortExpr.Equals("lastpostdate desc") AndAlso Not sortExpr.Equals("viewcount") AndAlso _
            Not sortExpr.Equals("viewcount asc") AndAlso Not sortExpr.Equals("viewcount desc") AndAlso _
            Not sortExpr.Equals("replycount") AndAlso Not sortExpr.Equals("replycount asc") AndAlso _
            Not sortExpr.Equals("replycount desc") AndAlso Not sortExpr.Equals("addeddate") AndAlso _
            Not sortExpr.Equals("addeddate asc") AndAlso Not sortExpr.Equals("addeddate desc") AndAlso _
            Not sortExpr.Equals("addedby") AndAlso Not sortExpr.Equals("addedby asc") AndAlso _
            Not sortExpr.Equals("addedby desc") AndAlso Not sortExpr.Equals("title") AndAlso _
            Not sortExpr.Equals("title asc") AndAlso Not sortExpr.Equals("title desc") AndAlso _
            Not sortExpr.Equals("lastpostby") AndAlso Not sortExpr.Equals("lastpostby asc") AndAlso _
            Not sortExpr.Equals("lastpostby desc") Then

            sortExpr = "lastpostdate desc"
        End If
        If Not sortExpr.StartsWith("_posts") Then
            sortExpr = "_posts." & sortExpr
        End If
        If Not sortExpr.StartsWith("_products.lastpostdate") Then
            sortExpr += ", LastPostDate DESC"
        End If
        Return sortExpr
    End Function

    ' Returns a new ForumDetails instance filled with the DataReader's current record data
    Public Overridable Function GetForumFromReader(ByVal reader As Common.DbDataRecord) As DataTypes.ForumDetails
        Return New DataTypes.ForumDetails( _
           CStr(reader("ForumID")), _
           CDate(reader("AddedDate")), _
           reader("AddedBy").ToString(), _
           reader("Title").ToString(), _
           CBool(CYesNoToBool(reader("Moderated"))), _
           CInt(reader("Importance")), _
           reader("Description").ToString(), _
           reader("ImageUrl").ToString())
    End Function

    ' Returns a collection of ForumDetails objects with the data read from the input DataReader
    Public Overridable Function GetForumCollectionFromReader(ByVal reader As Generic.List(Of Common.DbDataRecord)) As List(Of DataTypes.ForumDetails)
        Dim forums As New List(Of DataTypes.ForumDetails)
        For Each readerItem As Common.DbDataRecord In reader
            forums.Add(GetForumFromReader(readerItem))
        Next
        Return forums
    End Function

    ' Returns a new PostDetails instance filled with the DataReader's current record data
    Public Overridable Function GetPostFromReader(ByVal reader As Common.DbDataRecord) As DataTypes.PostDetails
        Return GetPostFromReader(reader, True)
    End Function

    Public Overridable Function GetPostFromReader(ByVal reader As Common.DbDataRecord, ByVal readBody As Boolean) As DataTypes.PostDetails
        Dim post As New DataTypes.PostDetails
        post.ID = reader("PostID").ToString
        post.AddedDate = CDate(reader("AddedDate"))
        post.AddedBy = reader("AddedBy").ToString()
        post.AddedByIP = reader("AddedByIP").ToString()
        post.ForumID = reader("ForumID").ToString
        post.ForumTitle = reader("ForumTitle").ToString()
        post.ParentPostID = reader("ParentPostID").ToString
        post.Title = reader("Title").ToString()
        If readBody Then
            post.Body = reader("Body").ToString()
        Else
            post.Body = String.Empty
        End If
        post.Approved = CYesNoToBool(reader("Approved"))
        post.Closed = CYesNoToBool(reader("Closed"))
        post.ViewCount = CInt(reader("ViewCount"))
        post.ReplyCount = CInt(reader("ReplyCount"))
        post.LastPostDate = CDate(reader("LastPostDate"))
        post.LastPostBy = reader("LastPostBy").ToString()

        Return post
    End Function

    ' Returns a collection of PostDetails objects with the data read from the input DataReader
    Public Overridable Function GetPostCollectionFromReader(ByVal reader As Generic.List(Of Common.DbDataRecord)) As List(Of DataTypes.PostDetails)
        Return GetPostCollectionFromReader(reader, True)
    End Function

    Public Overridable Function GetPostCollectionFromReader(ByVal reader As Generic.List(Of Common.DbDataRecord), ByVal readBody As Boolean) As List(Of DataTypes.PostDetails)
        Dim posts As New List(Of DataTypes.PostDetails)
        For Each readerItem As Common.DbDataRecord In reader
            posts.Add(GetPostFromReader(readerItem, readBody))
        Next
        Return posts
    End Function

    Private Function CYesNoToBool(ByVal InputString As String) As Boolean
        If InputString.ToLower = "y" Then
            Return True
        Else
            Return False
        End If
    End Function
End Class

